package com.school.sdk.haikang.helper;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;

public class AES {
    private AES() {
    }

    // 加密算法
    private static final String ALG = "AES";
    // 字符编码
    private static final Charset ENC = StandardCharsets.UTF_8;
    // 密钥正规化算法
    private static final String SEC_NORMALIZE_ALG = "MD5";

    private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";

    private static final String CIPHER_CBC_ALGORITHM = "AES/CBC/PKCS5Padding";

    // 加密
    public static String encrypt(String secret, String data) throws Exception {
        MessageDigest dig = MessageDigest.getInstance(SEC_NORMALIZE_ALG);
        byte[] key = dig.digest(secret.getBytes(ENC));
        SecretKeySpec secKey = new SecretKeySpec(key, ALG);

        Cipher aesCipher = Cipher.getInstance(ALG);
        byte[] byteText = data.getBytes(ENC);
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(secret.getBytes());
        aesCipher.init(Cipher.ENCRYPT_MODE, secKey, random);
        byte[] byteCipherText = aesCipher.doFinal(byteText);

        return new String(Base64.getEncoder().encode(byteCipherText), ENC);
    }

    // 解密
    public static String decrypt(String secret, String ciphertext) throws Exception {
        MessageDigest dig = MessageDigest.getInstance(SEC_NORMALIZE_ALG);
        byte[] key = dig.digest(secret.getBytes(ENC));
        SecretKeySpec secKey = new SecretKeySpec(key, ALG);
        Cipher aesCipher = Cipher.getInstance(ALG);
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(secret.getBytes());
        aesCipher.init(Cipher.DECRYPT_MODE, secKey, random);
        byte[] cipherbytes = Base64.getDecoder().decode(ciphertext.getBytes());
        byte[] bytePlainText = aesCipher.doFinal(cipherbytes);
        return new String(bytePlainText, ENC);
    }


    /**
     * AES加密ECB模式PKCS5Padding填充方式
     *
     * @param data 字符串
     * @param key  密钥
     * @return 加密字符串
     * @throws Exception 异常信息
     */
    public static String aes256ECBPkcs7Encrypt(String data, String key) throws Exception {
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        byte[] keyBytes = key.getBytes(ENC);
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, ALG));
        byte[] doFinal = cipher.doFinal(data.getBytes(ENC));
        return new String(Base64.getEncoder().encode(doFinal));
    }

    /**
     * AES解密ECB模式PKCS5Padding填充方式
     *
     * @param data 字符串
     * @param key  密钥
     * @return 解密字符串
     * @throws Exception 异常信息
     */
    public static String aes256ECBPkcs7Decrypt(String data, String key) throws Exception {
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        byte[] keyBytes = key.getBytes(ENC);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, ALG));
        byte[] doFinal = cipher.doFinal(Base64.getDecoder().decode(data));
        return new String(doFinal);
    }


    /**
     * AES加密CBC模式PKCS5Padding填充方式
     *
     * @param data 字符串
     * @param key  密钥
     * @param iv   偏移量
     * @return 加密字符串
     * @throws Exception 异常信息
     */
    public static String aes256CBCPkcs5Encrypt(String data, String key, String iv) throws Exception {
        Cipher cipher = Cipher.getInstance(CIPHER_CBC_ALGORITHM);
        byte[] keyBytes = key.getBytes(ENC);

        byte[] initParam = iv.getBytes(ENC);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);

        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, ALG), ivParameterSpec);
        byte[] doFinal = cipher.doFinal(data.getBytes(ENC));
        return new String(Base64.getEncoder().encode(doFinal));
    }

    /**
     * AES解密CBC模式PKCS5Padding填充方式
     *
     * @param data 字符串
     * @param key  密钥
     * @param iv   偏移量
     * @return 解密字符串
     * @throws Exception 异常信息
     */
    public static String aes256CBCPkcs5Decrypt(String data, String key, String iv) throws Exception {
        Cipher cipher = Cipher.getInstance(CIPHER_CBC_ALGORITHM);
        byte[] keyBytes = key.getBytes(ENC);
        byte[] initParam = iv.getBytes(ENC);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, ALG), ivParameterSpec);
        byte[] doFinal = cipher.doFinal(Base64.getDecoder().decode(data));
        return new String(doFinal);
    }

/* NOSONAR
    public static void main(String[] args) {//NOSONAR
        long reqTimestamp = Instant.now().getEpochSecond();
        String mac = "455";
        String ser = RandomStringUtil.getRandomNumber(6);

        String signStr = String.valueOf(reqTimestamp).concat("&")
                .concat(mac).concat("&")
                .concat(ser);
        try {
            String sign = AES.aes256ECBPkcs7Encrypt(signStr,"!*&1sf1&!@13&ecb");
            System.out.println("timestamp:"+reqTimestamp);
            System.out.println("mac:"+mac);
            System.out.println("ser:"+ser);
            System.out.println("sign:"+sign);
            System.out.println("qrcode:"+"type=ecard&code="+sign);


            String descStr = AES.aes256ECBPkcs7Decrypt("4TayCKcSGtDoHMZbH8hMrKwNfhE+ES9AUpwCMrOwxr4=","!*&1sf1&!@13&ecb");
            System.out.println("descStr:"+descStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    */
}